import datetime

from nicegui import background_tasks, events, ui
from orm import manager
from matplotlib import pyplot as plt


class History_chart:
    def show_diagram(self, chartname, xaxisNames, yaxisName, data):
        print(data)
        xaxisNames = [str(x) for x in xaxisNames]
        print(xaxisNames)
        ui.chart({
            "chart": {
                "type": 'column'
            },
            "title": {
                "text": chartname,
            },
            "xAxis": {
                "categories": xaxisNames,
                "crosshair": True,
            },
            "yAxis": {
                "min": 0,
                "title": {
                    "text": yaxisName
                }
            },
            "tooltip": {
                "valueSuffix": ''
            },
            "plotOptions": {
                "column": {
                    "pointPadding": 0.2,
                    "borderWidth": 0
                }
            },
            "series": [
                {
                    "name": '该用户',
                    "data": data
                }
            ]
        }).classes("w-full")

    def __init__(self, user_id) -> None:
        self.history = manager.get_histroy(user_id)
        self.amount_chart = ui.row().classes('mx-auto w-[500px] justify-end')
        self.accuracy_chart = ui.row().classes('mx-auto w-[500px] justify-end')

    def create_accuracy_chart(self) -> ui.row:
        with self.accuracy_chart:
            ui.toggle({1: '月', 2: '周'}, value=1, on_change=self.handle_accuracy).props('inline')
            # bar_colors = self.get_bar_color(1)
            x, y = self.calculate_accuracy(1)
            # with ui.pyplot(figsize=(3, 2)).classes('w-[500px]'):
            #     plt.bar(x, y, color=bar_colors)
            self.show_diagram("准确率分析", x, "准确率", y)
        return self.accuracy_chart

    def handle_accuracy(self, e: events.ValueChangeEventArguments) -> None:
        async def handle_accuracy():
            mode = e.value
            self.accuracy_chart.clear()
            with self.accuracy_chart:
                ui.toggle({1: '月', 2: '周'}, value=mode, on_change=self.handle_accuracy).props('inline')
                bar_colors = self.get_bar_color(mode)
                x, y = self.calculate_accuracy(mode)
                # with ui.pyplot(figsize=(3, 2)).classes('w-[500px]'):
                #     plt.bar(x, y, color=bar_colors)
                self.show_diagram("准确率分析", x, "准确率", y)

        background_tasks.create_lazy(handle_accuracy(), name='handle_accuracy')

    def create_amount(self) -> ui.row:
        with self.amount_chart:
            ui.toggle({1: '月', 2: '周'}, value=1, on_change=self.handle_amount).props('inline')
            x, y = self.calculate_sum(1)
            # bar_colors = self.get_bar_color(1)
            # with ui.pyplot(figsize=(3, 2)).classes('w-[500px]'):
            #     plt.bar(x, y, color=bar_colors)
            self.show_diagram("做题数量分析", x, "做题数量", y)
        return self.amount_chart

    def handle_amount(self, e: events.ValueChangeEventArguments) -> None:
        async def handle_amount():
            mode = e.value
            self.amount_chart.clear()
            with self.amount_chart:
                ui.toggle({1: '月', 2: '周'}, value=mode, on_change=self.handle_amount).props('inline')
                x, y = self.calculate_sum(mode)
                # bar_colors = self.get_bar_color(mode)
                # with ui.pyplot(figsize=(3, 2)).classes('w-[500px]'):
                #     plt.bar(x, y, color=bar_colors)
                self.show_diagram("做题数量分析", x, "做题数量", y)

        background_tasks.create_lazy(handle_amount(), name='handle_amount')

    def calculate_sum(self, mode):
        x = []
        y = []
        if mode == 1:
            x = range(1, 13)
            for i in range(1, 13):
                y.append(0)
            for item in self.history:
                d = item.time
                if d.year == datetime.datetime.now().date().year:
                    y[d.month - 1] = y[d.month - 1] + 1
        elif mode == 2:
            for i in range(7, 0, -1):
                previous_date = datetime.datetime.now() - datetime.timedelta(days=(i - 1))
                x.append(str(previous_date.date().month) + '.' + str(previous_date.date().day))
                y.append(0)
            for item in self.history:
                d = item.time
                difference = abs(datetime.datetime.now().date() - d.date())
                days_difference = difference.days
                if days_difference <= 6:
                    y[6 - days_difference] = y[6 - days_difference] + 1
        return x, y

    def calculate_accuracy(self, mode):
        x = []
        y = []
        accurate = []
        sum = []
        if mode == 1:
            for i in range(1, 13):
                x = range(1, 13)
                y.append(0)
                accurate.append(0)
                sum.append(0)
            for item in self.history:
                d = item.time
                if d.year == datetime.datetime.now().date().year:
                    sum[d.month - 1] = sum[d.month - 1] + 1
                    if item.score == 100:
                        accurate[d.month - 1] = accurate[d.month - 1] + 1
            for i in range(0, 12):
                if sum[i] != 0:
                    y[i] = accurate[i] / sum[i]
        else:
            for i in range(7, 0, -1):
                previous_date = datetime.datetime.now() - datetime.timedelta(days=(i - 1))
                x.append(str(previous_date.date().month) + '.' + str(previous_date.date().day))
                y.append(0)
                accurate.append(0)
                sum.append(0)
            for item in self.history:
                d = item.time
                difference = abs(datetime.datetime.now().date() - d.date())
                days_difference = difference.days
                if days_difference <= 6:
                    sum[6 - days_difference] = sum[6 - days_difference] + 1
                    if item.score == 100:
                        accurate[6 - days_difference] = accurate[6 - days_difference] + 1
            for i in range(0, 7):
                if sum[i] != 0:
                    y[i] = accurate[i] / sum[i]
        return x, y

    def get_bar_color(self, mode):
        bar_colors = []
        if mode == 1:
            t = 12
        else:
            t = 7
        for i in range(0, t):
            if i % 2 == 0:
                bar_colors.append('tab:red')
            else:
                bar_colors.append('tab:blue')
        return bar_colors
